import isArray from '@/base/isArray'
import isFunction from '@/base/isFunction'
import isString from '@/base/isString'
import isNullable from '@/base/isNullable'

/**
 * 根据数组 从对象中获取属性，并且以｜进行分割
 * @param {object} object
 * @param {string|string[]} properties
 * @returns {*}
 */
export const getPropValue = (object, properties) => {
  if (isString(properties)) return object?.[properties]
  return properties
    .map(prop => object?.[prop])
    .filter(Boolean)
    .join(`|`)
}

/**
 * 将数组转成Map类型
 * @param {Object[]} array 数组
 * @param {string|Function|string[]} [property] 主键
 * @param {{valueType?: 'object' | 'array', retainKeyWithNull?: boolean}} [options] 是否保留未定义的属性值
 * @return {Map<any, any>|{}|*}
 * @example
 *
 * const list = [
 *  {empId: 1, empName: '蔡徐坤'},
 *  {empId: 2, empName: '小明'}
 * ]
 * arrayToMap(list, 'empId')
 * =>
   [[Entries]]
    0: {1 => Object}
    1: {2 => Object}
   size:2
 *
 * const list = [
 *  1, 2, 3, '4'
 * ]
 * arrayToMap(list)
   =>
   [[Entries]]
   0: {1 => 1}
   1: {2 => 2}
   2: {3 => 3}
   3: {'4' => '4'}
   size:4
 *
 */
function arrayToMap(array = [], property, options = { valueType: 'object', retainKeyWithNull: false }) {
  if (isArray(array)) {
    // 如果property是Function
    if (isFunction(property)) {
      const map = new Map()
      array.forEach((v, vi) => property(map, v, vi))
      return map
    }
    const valueType = String(options?.valueType).toLowerCase() || 'object'
    // 非Function，且property存在
    if (property) {
      return array.reduce((pre, cur) => {
        let value = getPropValue(cur, property)
        if (options.retainKeyWithNull && isNullable(value)) value = 'undefined'
        if (value) {
          if (valueType === 'array') {
            if (!isArray(pre.get(value))) pre.set(value, [])
            pre.get(value).push(cur)
          } else {
            pre.set(value, cur)
          }
        }
        return pre
      }, new Map())
    }
    // property不存在时
    return array.reduce((pre, cur) => {
      if (options.retainKeyWithNull && isNullable(value)) cur = 'undefined'
      if (cur) {
        if (valueType === 'array') {
          if (!isArray(pre.get(cur))) pre.set(cur, [])
          pre.get(cur).push(cur)
        } else {
          pre.set(cur, cur)
        }
      }
      return pre
    }, new Map())
  }
  return new Map()
}
export default arrayToMap

/**
 * @example
 */
/**
// 多个属性名
const list = [
  { empId: 1, empName: '蔡徐坤' },
  { empId: 2, empName: '小明' },
  { empId: 3, empName: '蔡徐坤' },
]
console.log(arrayToMap(list, ['empId', 'empName']))
// =>
// [
//  ['1|蔡徐坤', {empId: 1, empName: '蔡徐坤'}],
//  ['2|小明', {empId: 2, empName: '小明'}],
//  ['3|蔡徐坤', {empId: 3, empName: '蔡徐坤'}]
// ]


// 单个属性名
const list2 = [
  { empId: 1, empName: '蔡徐坤' },
  { empId: 2, empName: '小明' },
  { empId: 3, empName: '蔡徐坤' },
]
console.log(arrayToMap(list2, 'empId'))
// =>
// [
//  ['1', {empId: 1, empName: '蔡徐坤'}],
//  ['2', {empId: 2, empName: '小明'}],
//  ['3', {empId: 3, empName: '蔡徐坤'}]
// ]

const list3 = [1, 2, 3, '4']
console.log(arrayToMap(list3));
// =>
// [
//   [1, 1]
//   [2, 2],
//   [3, 3],
//   [4, '4']
// ]
 */
